use idgen::IDGen;
use serde::{Deserialize, Serialize};
use sqlx::{sqlite::SqliteRow, Row};

use crate::utils::{date_util::get_now_time_m, mysql_utils::get_connect};

#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct BookName {
    pub id: String,
    pub content: String,
    pub title: String,
    pub use_time: i64,
    pub create_time: i64,
    pub creator_lid: String,
    pub creator_name: String,
    pub updater_lid: String,
    pub updater_name: String,
    pub up_ver: i16,
    pub sort: i16,
    pub tenant_id: i64,
    pub deleted: i64,
    pub update_time: i64,
}

impl Default for BookName {
    fn default() -> Self {
        BookName {
            id: "0".to_string(),
            content: String::from(""),
            title: String::from(""),
            use_time: 0,
            create_time: 0,
            creator_lid: String::from(""),
            creator_name: String::from(""),
            updater_lid: String::from(""),
            updater_name: String::from(""),
            up_ver: 0,
            sort: -1,
            tenant_id: 0,
            deleted: 0,
            update_time: 0,
        }
    }
}

pub async fn get_info_by_id(id: String) -> Option<BookName> {
    let mut conn = get_connect()
        .acquire()
        .await
        .expect("Error get_connect from db pool");
    let rust = sqlx::query(
        "select id, title, content, create_time, update_time from book_name where id = ?",
    )
    .bind(id)
    .map(|row: SqliteRow| {
        let mut group_type = BookName::default();
        group_type.id = row.get(0);
        group_type.title = row.get(1);
        group_type.content = row.get(2);
        group_type.create_time = row.get(3);
        group_type.update_time = row.get(4);
        group_type
    })
    .fetch_all(&mut *conn)
    .await;
    match rust {
        Ok(rest) => {
            if let Some(res) = rest.get(0) {
                return Some(res.clone());
            }
            return None;
        }
        Err(e) => {
            log::info!("get_info_by_id失败{}", e);
            return None;
        }
    }
}

pub async fn get_info_by_title(title: String) -> Option<BookName> {
    let mut conn = get_connect()
        .acquire()
        .await
        .expect("Error get_connect from db pool");
    let rust = sqlx::query(
        "select id, title, content, create_time, update_time from book_name where title = ?",
    )
    .bind(title)
    .map(|row: SqliteRow| {
        let mut group_type = BookName::default();
        group_type.id = row.get(0);
        group_type.title = row.get(1);
        group_type.content = row.get(2);
        group_type.create_time = row.get(3);
        group_type.update_time = row.get(4);
        group_type
    })
    .fetch_all(&mut *conn)
    .await;
    match rust {
        Ok(rest) => {
            if let Some(res) = rest.get(0) {
                return Some(res.clone());
            }
            return None;
        }
        Err(e) => {
            log::info!("get_info_by_title失败{}", e);
            return None;
        }
    }
}

pub async fn get_page(
    page_num: i64,
    page_size: i64,
    mut key_word: String,
) -> Option<(i64, Vec<BookName>)> {
    let mut conn = get_connect()
        .acquire()
        .await
        .expect("Error get_connect from db pool");
    let mut sql = "select id, title, content, create_time, update_time from book_name".to_string();
    let mut count = "select count(1) from group_type".to_string();
    if !key_word.is_empty() {
        sql += " where title like ? or content like ?";
        count += " where title like ? or content like ?";
    }
    sql += " order by sort asc, id DESC limit ?, ?";
    let mut count_query = sqlx::query_scalar(count.as_str());
    if !key_word.is_empty() {
        key_word = format!("%{}%", key_word);
        count_query = count_query.bind(key_word.clone()).bind(key_word.clone());
    }

    let rust: Result<i64, sqlx::Error> = count_query.fetch_one(&mut *conn).await;
    let mut count = 0;
    match rust {
        Ok(num) => {
            count = num;
            log::info!("count   {}", count);
        }
        Err(e) => {
            log::info!("get_page失败{}", e);
            return None;
        }
    }
    if count == 0 {
        return Some((count, vec![]));
    }

    let mut query = sqlx::query(sql.as_str());
    if !key_word.is_empty() {
        query = query.bind(key_word.clone()).bind(key_word);
    }
    let last = page_num * page_size;
    query = query.bind(last - page_size).bind(last);

    let rust = query
        .map(|row: SqliteRow| {
            let mut group_type = BookName::default();
            group_type.id = row.get(0);
            group_type.title = row.get(1);
            group_type.content = row.get(2);
            group_type.create_time = row.get(3);
            group_type.update_time = row.get(4);
            group_type
        })
        .fetch_all(&mut *conn)
        .await;
    match rust {
        Ok(rest) => {
            return Some((count, rest));
        }
        Err(e) => {
            log::info!("get_page失败{}", e);
            return None;
        }
    }
}

pub async fn get_list() -> Option<Vec<BookName>> {
    let mut conn = get_connect()
        .acquire()
        .await
        .expect("Error get_connect from db pool");
    let rust = sqlx::query(
        "select id, title, content, create_time, update_time from book_name order by sort asc, id DESC",
    )
    .map(|row: SqliteRow| {
        let mut group_type = BookName::default();
        group_type.id = row.get(0);
        group_type.title = row.get(1);
        group_type.content = row.get(2);
        group_type.create_time = row.get(3);
        group_type.update_time = row.get(4);
        group_type
    })
    .fetch_all(&mut *conn)
    .await;
    match rust {
        Ok(rest) => {
            return Some(rest);
        }
        Err(e) => {
            log::info!("get_list失败 {}", e);
            return None;
        }
    }
}

#[tokio::main]
pub async fn save(info: BookName) -> Option<u64> {
    if info.id == '1'.to_string() {
        log::info!("save创建数据失败 id不能为-1");
        return None;
    }
    let mut conn = get_connect()
        .acquire()
        .await
        .expect("Error get_connect from db pool");
    let now = get_now_time_m();
    let data = get_info_by_title(info.title.clone()).await;
    let id: u64;
    if data.is_none() {
        let idgen = IDGen::new(1);
        id = idgen.new_id();
        let result = sqlx::query("insert into book_name (id,content,title,create_time,creator_lid,creator_name,updater_lid,updater_name,up_ver,sort,tenant_id,deleted,update_time, use_time) values (?,?,?,?,?,?,?,?,?,?,?,?,?,?)")
        .bind(id.to_string())
        .bind(info.content)
        .bind(info.title)
        .bind(now)
        .bind(info.creator_lid)
        .bind(info.creator_name)
        .bind(info.updater_lid)
        .bind(info.updater_name)
        .bind(info.up_ver)
        .bind(info.sort)
        .bind(info.tenant_id)
        .bind(info.deleted)
        .bind(now)
        .bind(now)
        .execute(&mut *conn)
        .await;

        match result {
            Ok(_) => {
                log::info!("创建数据成功");
                return Some(id);
            }
            Err(e) => {
                log::info!("{}", e);
                log::info!("save创建数据失败");
                return None;
            }
        }
    }
    log::info!("group_type 存在！");
    return None;
}



pub async fn update_sort_tokio(info: BookName) -> bool {
    if info.id == '1'.to_string() {
        return true;
    }
    let mut conn = get_connect()
        .acquire()
        .await
        .expect("Error get_connect from db pool");
    let now = get_now_time_m();

    let result = sqlx::query("UPDATE book_name SET update_time = ?, sort = ? where id = ?")
    .bind(now)
    .bind(info.sort)
    .bind(info.id)
    .execute(&mut *conn)
    .await;
    match result {
        Ok(_) => {
            log::info!("更新数据成功");
            return true;
        }
        Err(e) => {
            log::info!("{}", e);
            log::info!("更新数据失败");
            return false;
        }
    }
}


pub async fn update_title_tokio(info: BookName) -> bool {
    if info.id == '1'.to_string() {
        return true;
    }
    let mut conn = get_connect()
        .acquire()
        .await
        .expect("Error get_connect from db pool");
    let now = get_now_time_m();

    let result = sqlx::query("UPDATE book_name SET update_time = ?, title = ? where id = ?")
    .bind(now)
    .bind(info.title)
    .bind(info.id)
    .execute(&mut *conn)
    .await;
    match result {
        Ok(_) => {
            log::info!("更新数据成功");
            return true;
        }
        Err(e) => {
            log::info!("{}", e);
            log::info!("更新数据失败");
            return false;
        }
    }
}


pub async fn delete_by_id(id: String) -> bool {
    if id == '1'.to_string() {
        log::info!("默认不能删除");
        return false;
    }
    log::info!("{}", id);
    let mut conn = get_connect()
        .acquire()
        .await
        .expect("Error get_connect from db pool");
    let result = sqlx::query("delete from book_name where id = ?")
        .bind(id)
        .execute(&mut *conn)
        .await;

    match result {
        Ok(_) => {
            println!("删除数据成功 {:?}", result);
            return true;
        }
        Err(e) => {
            println!("{}", e);
            println!("删除数据失败");
            return false;
        }
    }
}
